package net.atomarrow.domains;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.alibaba.fastjson.annotation.JSONField;
import net.atomarrow.aop.InterceptorKeeper;
import net.atomarrow.configs.DbConfig;
import net.atomarrow.configs.scan.ConfigScanner;
import net.atomarrow.db.orm.OrmContext;
import net.atomarrow.ioc.ActionContext;
import net.atomarrow.ioc.ApplicationContext;
import net.atomarrow.services.IService;
import net.atomarrow.services.Service;
import net.atomarrow.util.BeanUtil;


public class Domain implements Serializable{
	/**
	 * 需要更新的列
	 */
    private Set<String> updateFieldSet=new HashSet<String>();
    /**
     * 不需要进行更新列检测
     */
    @JSONField(serialize=false)
    private boolean updateNotNeedCheck;

	public void generateTable(){
		ActionContext.init(null, null, null,null);
		ActionContext.getContext().setNeedTx(true);
		ApplicationContext.load(new InterceptorKeeper());
		ApplicationContext.load(new Service());
		ApplicationContext.load(new ConfigScanner());
		IService service = ApplicationContext.get(Service.class);
		DbConfig config = ApplicationContext.get(DbConfig.class);
		ConfigScanner scanner = ApplicationContext.get(ConfigScanner.class);
		scanner.scan();
		DbMaker dm=new DbMaker(DbConfig.getDatabaseName());
		String className =Thread.currentThread().getStackTrace()[2].getClassName();
		String simpleName = className.substring(className.lastIndexOf(".")+1);
		dm.makeTable(simpleName,OrmContext.getDomainClass(simpleName), service);
		ActionContext.destory();
	}
	
	
	public void generateAllSingleTable(){
	    ActionContext.init(null, null, null,null);
	    ActionContext.getContext().setNeedTx(true);
	    ApplicationContext.load(new InterceptorKeeper());
	    ApplicationContext.load(new Service());
	    ApplicationContext.load(new ConfigScanner());
	    IService service = ApplicationContext.get(Service.class);
	    DbConfig config = ApplicationContext.get(DbConfig.class);
	    ConfigScanner scanner = ApplicationContext.get(ConfigScanner.class);
	    scanner.scan();
	    DbMaker dm=new DbMaker(DbConfig.getDatabaseName());
	    List<String> domainNames = OrmContext.getSingleTableDomainNames();
	    for(String domainName:domainNames){
	        dm.makeTable(domainName,OrmContext.getDomainClass(domainName), service);
	    }
	    ActionContext.destory();
	}
	public void generateAllMultiTable(int id){
        ActionContext.init(null, null, null,null);
        ActionContext.getContext().setNeedTx(true);
        ApplicationContext.load(new InterceptorKeeper());
        ApplicationContext.load(new Service());
        ApplicationContext.load(new ConfigScanner());
        IService service = ApplicationContext.get(Service.class);
        DbConfig config = ApplicationContext.get(DbConfig.class);
        ConfigScanner scanner = ApplicationContext.get(ConfigScanner.class);
        scanner.scan();
        DbMaker dm=new DbMaker(DbConfig.getDatabaseName());
        List<String> domainNames = OrmContext.getMultipleTableDomainNames();
        for(String domainName:domainNames){
            dm.makeTable(DomainUtil.getMultiTableName(domainName, id),OrmContext.getDomainClass(domainName), service);
        }
        ActionContext.destory();
	}
	
	public void addUpdateField(String filedName){
		updateFieldSet.add(filedName);
	}
	public void setUpdateField(Set<String> set){
		updateFieldSet=set;
	}
	
	public boolean isNeedUpdate(String filedName){
		return updateFieldSet.contains(filedName);
	}
	
	public void setNull(String filedName){
		BeanUtil.setFieldValue(this, filedName, null);
		addUpdateField(filedName);
	}
	public void setUpdateNotNeedCheck(Boolean updateNotNeedCheck) {
		this.updateNotNeedCheck = updateNotNeedCheck;
	}
	public boolean getUpdateNotNeedCheck() {
		return updateNotNeedCheck;
	}
	public void checkChange(){
		if(updateNotNeedCheck){
			return;
		}
		Field[] fields = this.getClass().getDeclaredFields();
		for(Field field:fields){
			try {
				if (!Modifier.isPublic(field.getModifiers())
						|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
					field.setAccessible(true);
				}
				if(field.get(this)!=null){
					addUpdateField(field.getName());
				}
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
}
